package jp.co.redfox.archclub.poker.hand;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import jp.co.redfox.archclub.poker.Card;
import jp.co.redfox.archclub.poker.Hand;

public class NumOfKind implements HandRestriction {

    private int[] numbers;

    public NumOfKind(int... numbers) {
        this.numbers = numbers;
    }

    @Override
    public boolean matches(Hand hand) {
        List<Card> cards = new ArrayList<>();
        cards.addAll(hand.getCards());
        for (int number : numbers) {
            List<Card> matched = submatches(cards, number);
            if (matched == null)
                return false;
            else
                cards.removeAll(matched);
        }
        return true;
    }

    private List<Card> submatches(List<Card> cards, int number) {
        Map<String, List<Card>> candidates = new HashMap<>();
        for (Card card : cards)
            if (!candidates.containsKey(card.getNumber())) {
                List<Card> candidate = new ArrayList<>();
                candidate.add(card);
                candidates.put(card.getNumber(), candidate);
            } else {
                candidates.get(card.getNumber()).add(card);
            }

        for (List<Card> candidate : candidates.values())
            if (candidate != null && candidate.size() == number)
                return candidate;
        return null;
    }

    @Override
    public int getRequiredNumber(Hand hand) {
        List<Card> cards = new ArrayList<>();
        cards.addAll(hand.getCards());
        for (int number : numbers) {
            List<Card> matched = submatches(cards, number);
            if (matched != null)
                cards.removeAll(matched);
        }
        return numbers.length - hand.getCards().size() - cards.size();
    }

    @Override
    public Card[] getChangeCards(Hand hand) {
        List<Card> cards = new ArrayList<>();
        cards.addAll(hand.getCards());
        for (int number : numbers) {
            List<Card> matched = submatches(cards, number);
            if (matched != null)
                cards.removeAll(matched);
        }
        return cards.toArray(new Card[cards.size()]);

    }
}
